"""
Parse xmind to programmable data types.
"""

import json
import logging
import os
import sys
from zipfile import ZipFile
from typing import Union
from io import BytesIO

config = {'logName': __name__,
          'logLevel': None,
          'logFormat': '%(asctime)s %(levelname)-8s: %(message)s',
          'showTopicId': False,
          'hideEmptyValue': True}

cache = {}
_log_name = config['logName'] or __file__
_log_level = config['logLevel'] or logging.WARNING
_log_fmt = config['logFormat'] or '%(asctime)s %(levelname)-8s: %(message)s'

logger = logging.getLogger(_log_name)
logger.setLevel(_log_level)
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(logging.Formatter(config['logFormat']))
logger.addHandler(console_handler)


def set_logger_level(new_level):
    logger.setLevel(new_level)


def is_xmind_zen(file):
    """Determine if this is a xmind zen file type."""
    with ZipFile(file) as xmind:
        return 'content.json' in xmind.namelist()


def get_xmind_zen_builtin_json(file_path):
    """Read internal content.json from xmind zen file."""
    name = "content.json"
    with ZipFile(file_path) as xmind:
        if name in xmind.namelist():
            content = xmind.open(name).read().decode('utf-8')
            return json.loads(content)

        raise AssertionError("Not a xmind zen file type!")


def _get_out_file_name(xmind_file, suffix):
    assert isinstance(xmind_file, str) and xmind_file.endswith('.xmind'), "Invalid xmind file!"
    name = os.path.abspath(xmind_file[0:-5] + suffix)

    return name


def xmind_to_dict(file: Union[str, BytesIO]) -> dict:
    """
    打开并转换XMind文件为字典类型。

    根据文件类型（XMind Zen或旧版XMind）自动选择相应的解析器，
    将XMind文件解析为Python字典结构。支持文件路径或BytesIO对象作为输入。

    Args:
        file (Union[str, BytesIO]): XMind文件路径字符串或BytesIO对象

    Returns:
        dict: 包含XMind文件内容的字典结构，每个工作表作为一个元素存储在列表中

    Notes:
        - 自动检测XMind文件格式（Zen或旧版）
        - 对于Zen格式，使用.zenreader模块进行解析
        - 对于旧版格式，使用.xreader模块进行解析
    """
    if is_xmind_zen(file):
        from .zenreader import open_xmind, get_sheets, sheet_to_dict
    else:
        from .xreader import open_xmind, get_sheets, sheet_to_dict

    open_xmind(file)
    data = []

    for s in get_sheets():
        data.append(sheet_to_dict(s))

    return data


def xmind_to_file(file_path, file_type):
    if file_type == 'json':
        return xmind_to_json(file_path)

    elif file_type == 'xml':
        return xmind_to_xml(file_path)

    else:
        raise ValueError('Not supported file type: {}'.format(file_type))


def xmind_to_content(file_bytes: bytes, file_type: str) -> str:
    """
    将XMind文件字节数据转换为指定格式的内容字符串。

    根据指定的文件类型，将XMind文件的字节数据解析并转换为JSON或XML格式的字符串表示。

    Args:
        file_bytes (bytes): XMind文件的字节数据
        file_type (str): 目标输出格式，支持 'json' 或 'xml'

    Returns:
        str: 解析后的JSON或XML格式字符串

    Raises:
        ValueError: 当file_type不是支持的格式时抛出
    """
    if file_type == 'json':
        return xmind_bytes_to_json(file_bytes)

    elif file_type == 'xml':
        return xmind_bytes_to_xml(file_bytes)

    else:
        raise ValueError('Not supported file type: {}'.format(file_type))



def xmind_to_json(file_path):
    target = _get_out_file_name(file_path, 'json')

    with open(target, 'w', encoding='utf8') as f:
        f.write(json.dumps(xmind_to_dict(file_path), indent=2, ensure_ascii=False))

    return target


def xmind_bytes_to_json(file_bytes: bytes) -> str:
    """
    将XMind文件字节数据转换为JSON格式字符串。

    接收XMind文件的字节数据，将其解析为字典结构，然后转换为格式化的JSON字符串。

    Args:
        file_bytes (bytes): XMind文件的字节数据

    Returns:
        str: 格式化的JSON字符串，包含XMind文件的内容，使用2个空格缩进
    """
    return json.dumps(xmind_to_dict(BytesIO(file_bytes)), indent=2, ensure_ascii=False)


def xmind_to_xml(file_path):
    try:
        from dicttoxml import dicttoxml
        from xml.dom.minidom import parseString
        target = _get_out_file_name(file_path, 'xml')
        xml = dicttoxml(xmind_to_dict(file_path), custom_root='root')
        xml = parseString(xml.decode('utf8')).toprettyxml(encoding='utf8')

        with open(target, 'w', encoding='utf8') as f:
            f.write(xml.decode('utf8'))

        return target
    except ImportError:
        raise ImportError('Parse xmind to xml require "dicttoxml", try install via pip:\n' +
                          '> pip install dicttoxml')


def xmind_bytes_to_xml(file_bytes: bytes) -> str:
    """
    将XMind文件字节数据转换为XML格式字符串。

    接收XMind文件的字节数据，将其解析为字典结构，然后使用dicttoxml库转换为格式化的XML字符串。

    Args:
        file_bytes (bytes): XMind文件的字节数据

    Returns:
        str: 格式化的XML字符串，包含XMind文件的内容，使用UTF-8编码

    Raises:
        ImportError: 当缺少dicttoxml库时抛出，提示用户安装该库
    """
    try:
        from dicttoxml import dicttoxml
        from xml.dom.minidom import parseString
        xml = dicttoxml(xmind_to_dict(BytesIO(file_bytes)), custom_root='root')
        xml = parseString(xml.decode('utf8')).toprettyxml(encoding='utf8')
        return xml
    except ImportError:
        raise ImportError('Parse xmind to xml require "dicttoxml", try install via pip:\n' +
                          '> pip install dicttoxml')